﻿using System;
using System.Collections.Generic;
using System.Linq;
using Fuse8.DomainFramework.Common;
using Fuse8.DomainFramework.Common.Locator;

namespace Fuse8.DomainFramework.DataAccess.SqlDatabase
{
	/// <summary>
    /// Facade for <see cref="IEntityMappingConfigurator"/>
	/// </summary>
    public class SqlEntityHelper
	{
	    private static IEntityMappingConfiguratorChain _chain;
	    private static bool _mainConfiguratorSet;

	    /// <summary>
        /// Current configurator
        /// </summary>
		protected static IEntityMappingConfigurator MappingConfigurator
		{
			get
			{
                if (!_mainConfiguratorSet)
                {
                    var mappingConfigurator =
                     DependencyServiceLocator.Current.IsRegistered<IEntityMappingConfigurator>()
                         ? DependencyServiceLocator.Current.GetInstance<IEntityMappingConfigurator>()
                         : new DefaultEntityMappingConfigurator();
                    Chain.AddDefault(mappingConfigurator);
                    _mainConfiguratorSet = true;
                }
			    return Chain;
			}
		}

        private static IEntityMappingConfiguratorChain Chain
        {
            get
            {
                return _chain ??
                       (_chain =
                        DependencyServiceLocator.Current.IsRegistered<IEntityMappingConfiguratorChain>()
                            ? DependencyServiceLocator.Current.GetInstance<IEntityMappingConfiguratorChain>()
                            : new DefaultEntityMappingConfiguratorWithChain());
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="configurator"></param>
        public static void SetSuccessor(IEntityMappingConfigurator configurator)
        {
            Chain.Add(configurator);
        }

        /// <summary>
        /// Gets table name by type
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
		public static string GetEntityTableName<T>()
		{
			return GetEntityTableName(typeof (T));
		}

        /// <summary>
        /// Gets table name by type
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
		public static string GetEntityTableName(Type type)
		{
			return MappingConfigurator.GetEntityTableName(type);
		}

        /// <summary>
        /// Gets related property column name
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="property"></param>
        /// <returns></returns>
        public static string GetRelatedPropertyColumnName<T>(string property)
        {
            return GetRelatedPropertyColumnName(typeof (T), property);
        }

	    private static string GetRelatedPropertyColumnName(Type type, string property)
	    {
	        return MappingConfigurator.GetRelatedPropertyColumnName(type, property);
	    }

        /// <summary>
        /// Checks whether column situates in entity
        /// </summary>
        /// <param name="type"></param>
        /// <param name="column"></param>
        /// <returns></returns>
	    public static bool IsColumnInEntity(Type type, string column)
		{
			return type.GetProperty(column) != null;
		}

        /// <summary>
        /// Gets entity column alias
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="column"></param>
        /// <returns></returns>
		public static string GetEntityColumnAlias<T>(string column)
		{
			return GetEntityColumnAlias(typeof(T), column);
		}		

        /// <summary>
        /// Gets entity column alias
        /// </summary>
        /// <param name="type"></param>
        /// <param name="column"></param>
        /// <returns></returns>
		public static string GetEntityColumnAlias(Type type, string column)
		{
			return MappingConfigurator.GetEntityColumnAlias(type, column);
		}

        /// <summary>
        /// Gets list of ignored columns
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
		public static IEnumerable<string> GetIgnoredColumns<T>()
		{
			return GetIgnoredColumns(typeof(T));
		}

        /// <summary>
        /// Gets list of ignored columns
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
		public static IEnumerable<string> GetIgnoredColumns(Type type)
		{
			return MappingConfigurator.GetIgnoredColumns(type);
		}
	}
}